#pragma once
#include<vector>
#include"instruction_enum.h"
#include"operands.h"
#include"../Global.h"
#include"../OP_enum.h"

class instruction {
public:
    instruction(int8_t cond_reg_, bool v, int8_t hw_id, uint32_t type_, int8_t ldst) :
                cond_reg(cond_reg_), vector(v), dst_hw_id(hw_id), opcode(type_), ldst_mode(ldst) {
        operands = new std::vector<base_operand*>();
    }
    // instruction(int8_t cond_reg_, bool v, int8_t hw_id, uint32_t type_, int8_t ldst) :
    //             cond_reg(cond_reg_), vector(v), dst_hw_id(hw_id), opcode(type_) {
    //     ldst_mode = 0;
    //     operands = new std::vector<base_operand*>(1);
    // }
    instruction(int8_t cond_reg_, bool v, int8_t hw_id, uint32_t type_) :
                cond_reg(cond_reg_), vector(v), dst_hw_id(hw_id), opcode(type_) {
        ldst_mode = 0;
        operands = new std::vector<base_operand*>();
    }
    instruction(uint32_t type) : opcode(type) {
        operands = new std::vector<base_operand*>();
    }
    ~instruction() {
        for (auto op : *operands) {
            delete op;
        }
        delete operands;
    }
    void add_imme_op(uint64_t value);
    void add_register_op(int id);
    addr_size_t get_next_instr_addr(addr_size_t addr);
    uint32_t get_opcode();
    base_operand* get_operands(int index);
    int8_t  get_ldst_mode();
    int8_t  get_hw_id();
    void set_cond_reg(int8_t reg_id);
    void set_vector_flag(bool flag);
    void set_hw_id(int8_t hw_id);
    void set_opcode(uint32_t op);
    void set_ldst_mode(int8_t mode);

private:
    //!2025.02.06 此处将instr_type删掉，用每个硬件部件内部的opcode代替。因为该成员与opcode重复，节省内存
    // int     instr_type; 通过instruction enum来表示指令的操作类型
    int8_t  cond_reg;   //记录指令使用的条件寄存器编号，如果为000则表明为无条件指令（Z标识无需单独存储
    bool    vector;     //记录指令是否为向量指令，true -> 向量指令，false -> 标量指令
    //标识位P无需单独存储，instr_unit中的并行发射指令数N已包含该信息
    int8_t  dst_hw_id;  //在指令分析阶段通过分析OP值来确定该条指令该由哪个硬件部件执行计算，具体执行的操作应存储在下方成员中
    uint32_t    opcode; /*根据后续分发到的硬件部件，该成员存储硬件部件包含的可选操作码中的一种
                        （即在parsing阶段确定硬件部件后，继续解析op字段，将op解析为硬件部件中可选的一个enum成员（enum包含所有可选操作*/

    int8_t  ldst_mode;  //用于存储load/store指令的寻址方式，共12种，存储enum

    //!ATTENTION: vector内部的操作数应严格按照src1，src2，src3，dst的顺序存储
    std::vector<base_operand*>* operands; //通过vector存储一个指令包含的所有操作数，数量可能从0～3个
};

typedef struct {
    instruction* instr;
    addr_size_t head_addr;
    int para_instr_nums; //指明该条指令后与该指令并行发射的指令数 N
} instr_unit;
 typedef struct {
    addr_size_t head_addr;
    addr_size_t end_addr;
 }addr_unit;